﻿using System;

namespace CSW.Framework.Common
{
    /// <summary>
    /// AsyncProcessHelper
    /// </summary>
    public class AsyncProcessHelper
    {
        private readonly UpdateStatusDelegate m_UpdateStatus;
        private readonly Func<bool> m_ShouldCancel;
        private readonly FuncVoid<FuncVoid> m_UIThreadInvoker;

        /// <summary>
        /// Initializes a new instance of the <see cref="AsyncProcessHelper"/> class.
        /// </summary>
        /// <param name="updateStatus">The <see cref="UpdateStatusDelegate"/>.</param>
        /// <param name="shouldCancel">The method which determines if cancel has been requested.</param>
        /// <param name="uiThreadInvoker">The UI thread invoker.</param>
        public AsyncProcessHelper(UpdateStatusDelegate updateStatus, Func<bool> shouldCancel, FuncVoid<FuncVoid> uiThreadInvoker)
        {
            Guard.ArgumentNotNull(updateStatus, "updateStatus");
            Guard.ArgumentNotNull(shouldCancel, "shouldCancel");
            Guard.ArgumentNotNull(uiThreadInvoker, "uiThreadInvoker");

            m_UpdateStatus = updateStatus;
            m_ShouldCancel = shouldCancel;
            m_UIThreadInvoker = uiThreadInvoker;
        }

        /// <summary>
        /// Gets the <see cref="UpdateStatusDelegate"/>.
        /// </summary>
        /// <value>The <see cref="UpdateStatusDelegate"/>.</value>
        public UpdateStatusDelegate UpdateStatusDelegate
        {
            get { return m_UpdateStatus; }
        }

        /// <summary>
        /// Updates the status message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void UpdateStatus(string message)
        {
            m_UpdateStatus(null, message, null);
        }

        /// <summary>
        /// Updates the status message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="percentComplete">The percent complete.</param>
        public void UpdateStatus(string message, int percentComplete)
        {
            m_UpdateStatus(null, message, percentComplete);
        }

        /// <summary>
        /// Gets a value indicating whether cancel has been requested.
        /// </summary>
        /// <value><c>true</c> if cancel has been requested; otherwise, <c>false</c>.</value>
        public bool Cancel
        {
            get { return m_ShouldCancel(); }
        }

        /// <summary>
        /// Accesses the UI thread.
        /// </summary>
        /// <param name="method">The method to execute.</param>
        public void Invoke(FuncVoid method)
        {
            Guard.ArgumentNotNull(method, "method");

            m_UIThreadInvoker.Invoke(method);
        }
    }
}